﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Communication.UDPClient
{
    public delegate void UDPReceivedEventHandler(UdpStateEventArgs args);

    public class UDPClient
    {
        private UdpClient udpClient;

        /// <summary>
        /// 接收到消息时激发该事件
        /// </summary>
        public event UDPReceivedEventHandler UDPMessageReceived;

        /// <summary>
        /// 构造方法,构造完成后就可以收发信息，关闭后需要重新构建
        /// </summary>
        /// <param name="locateIP">本地IP地址</param>
        /// <param name="locatePort">本地端口</param>
        /// <param name="NeedReceiveData">接收数据</param>
        public UDPClient(string locateIP, int locatePort, bool NeedReceiveData = true)
        {
            IPAddress locateIp = IPAddress.Parse(locateIP);
            IPEndPoint locatePoint = new IPEndPoint(locateIp, locatePort);
            udpClient = new UdpClient(locatePoint);
            udpClient.Client.ReceiveBufferSize = 1024 * 1024;

            //监听创建好后，创建一个线程，开始接收信息    
            if (NeedReceiveData)
            {
                Task.Run(() =>
                {
                    Debug.WriteLine($"UdpClient启动数据接收线程");

                    while (true)
                    {
                        if (udpClient == null)
                        {
                            break;
                        }

                        try
                        {
                            IPEndPoint remotePoint = null;
                            var received = udpClient.Receive(ref remotePoint);
                            UdpStateEventArgs udpReceiveState = new UdpStateEventArgs
                            {
                                remoteEndPoint = remotePoint,
                                buffer = received
                            };

                            UDPMessageReceived?.Invoke(udpReceiveState);
                        }
                        catch (Exception ex)
                        {
                            Debug.WriteLine($"UDP接收任务发生异常:{ex.Message}");
                        }
                    }

                    Debug.WriteLine($"UdpClient 接收线程结束");
                });
            }
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="remoteIP">目标IP</param>
        /// <param name="remotePort">目标端口</param>
        /// <param name="buffer">数据</param>
        public void SendData(string remoteIP, int remotePort, byte[] buffer)
        {
            if (udpClient != null)
            {
                IPAddress remoteIp = IPAddress.Parse(remoteIP);
                IPEndPoint remotePoint = new IPEndPoint(remoteIp, remotePort);
                udpClient.Send(buffer, buffer.Length, remotePoint);
            }
            else
            {
                throw new Exception("连接已经关闭");
            }
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="remotePoint">目标连接点</param>
        /// <param name="buffer">数据</param>
        public void SendData(IPEndPoint remotePoint, byte[] buffer)
        {
            if (udpClient != null)
            {
                udpClient.Send(buffer, buffer.Length, remotePoint);
            }
            else
            {
                throw new Exception("连接已经关闭");
            }
        }

        /// <summary>
        /// 关闭连接
        /// </summary>
        public void CloseUDP()
        {
            udpClient?.Close();
            udpClient = null;
        }
    }
}
